home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / circuits / irsim-ca.2 / irsim-ca / irsim-cap-9.2 / src / irsim / incsim.c < prev    next >
C/C++ Source or Header  |  1994-07-21  |  44KB  |  1,958 lines

  1. /* 
  2.  *     ********************************************************************* 
  3.  *     * Copyright (C) 1988, 1990 Stanford University.                     * 
  4.  *     * Permission to use, copy, modify, and distribute this              * 
  5.  *     * software and its documentation for any purpose and without        * 
  6.  *     * fee is hereby granted, provided that the above copyright          * 
  7.  *     * notice appear in all copies.  Stanford University                 * 
  8.  *     * makes no representations about the suitability of this            * 
  9.  *     * software for any purpose.  It is provided "as is" without         * 
  10.  *     * express or implied warranty.  Export of this software outside     * 
  11.  *     * of the United States of America may require an export license.    * 
  12.  *     ********************************************************************* 
  13.  */
  14.  
  15. /*
  16.  * Incremental simulation
  17.  */
  18.  
  19. #include <stdio.h>
  20. #include "defs.h"
  21. #include "net.h"
  22. #include "globals.h"
  23.  
  24.  
  25. /*
  26.  * Set H to the next "effective" change in the history following Hp
  27.  */
  28. #define    NEXTH( H, Hp )                    \
  29.     for( (H) = (Hp)->next; (H)->punt; (H) = (H)->next )
  30.  
  31.  
  32. /*
  33.  * time at which history entry was enqueued
  34.  */
  35. #define    QTIME( H )        ( (H)->time - (H)->t.r.delay )
  36. #define    QPTIME( H )        ( (H)->time - (H)->t.p.delay )
  37. #define    PuntTime( H )        ( (H)->time - (H)->t.p.ptime )
  38.  
  39.  
  40. #define    IsDeviated( ND )    \
  41.     ( (ND)->nflags & (DEVIATED | CHANGED) or (ND)->events != NULL )
  42.  
  43. #define    NeedUpdate( ND )    \
  44.     ( ( (ND)->nflags & (ACTIVE_CL | STIM | POWER_RAIL) ) == 0 )
  45.  
  46.  
  47. public    long    INC_RES = 0;        /* time resolution in ticks (.5 ns) */
  48. public    nptr    inc_cause = (nptr) 1;    /* fake cause ptr for path command */
  49.  
  50. public    long    nevals = 0;        /* # of evaluations */
  51. public    long    i_nevals = 0;        /* # of incremental evaluations */
  52. private    long    o_nevals, o_nevent;
  53.  
  54. public    long    nreval_ev = 0;        /* number of various events */
  55. public    long    npunted_ev = 0;
  56. public    long    nstimuli_ev = 0;
  57. public    long    ncheckpt_ev = 0;
  58. public    long    ndelaychk_ev = 0;
  59. public    long    ndelay_ev = 0;
  60.  
  61. private    void    (*curr_model)();    /* the current model used to eval */
  62. private    hptr    modelp;            /* model history */
  63.  
  64. #ifdef FAULT_SIM
  65. #define    TRIGGER_EV    0x81
  66.  
  67. public    int    fault_mode = FALSE;    /* TRUE when doing faultsim */
  68. private    int    stop_early;        /* TRUE when fault detected */
  69. private    long    old_cur_delta;        /* cur_delta before faultsim */
  70. private    evptr    pending_evs;        /* pending events before faultsim */
  71. extern    int    do_trigger();
  72. extern    void    setup_triggers();
  73.  
  74. #define    DoingFault    ( fault_mode != FALSE )
  75. #define    NotDoingFault    ( fault_mode == FALSE )
  76. #else
  77. #define    DoingFault    (0)
  78. #define    NotDoingFault    (1)
  79. #define    hchange        head
  80. #endif
  81.  
  82.  
  83. typedef struct            /* transistor stage built by GetConnList */
  84.   {
  85.     int   flags;            /* see below */
  86.     nptr  nd_list;            /* the connection list */
  87.     nptr  inp_list;            /* input nodes connected to list */
  88.   } Stage, *pstg;
  89.  
  90.         /* stage flags */
  91. #define    ALL_MERGED    0x1        /* all nodes in stage are converged */
  92. #define    ONLY_INPUT    0x2        /* list consists of input node only */
  93. #define    INP_TRANS    0x4        /* there are switching inputs */
  94.  
  95.  
  96. /*
  97.  * Update the state of a node from the history.  Set the INPUT flag as well.
  98.  * Return a pointer to the next change in the history.
  99.  */
  100. private    hptr UpdateNode( nd )
  101.   register nptr  nd;
  102.   {
  103.     register hptr cur, nxt;
  104.  
  105.     cur = nd->curr;
  106.     if( cur->time > cur_delta )
  107.     cur = (hptr) &(nd->head);
  108.  
  109.     NEXTH( nxt, cur );
  110.     while( nxt->time <= cur_delta )
  111.       {
  112.     cur = nxt;
  113.     NEXTH( nxt, nxt );
  114.       }
  115.  
  116.     nd->curr = cur;
  117.     nd->npot = cur->val;
  118.     if( cur->inp )
  119.     nd->nflags |= INPUT;
  120.     else
  121.     nd->nflags &= ~INPUT;
  122.  
  123.     return( nxt );
  124.   }
  125.  
  126.  
  127. /*
  128.  * Activate a node: Set the ACTIVE_CL flag, schedule all pending transitions
  129.  * as of cur_delta.  Punted events that were already punted (as of cur_delta)
  130.  * remain in the history.  Pending punted events are rescheduled.  Punted
  131.  * events between nd->curr and the next transition that were queued after
  132.  * cur_delta are removed from the history and put in nd->t.punts.
  133.  */
  134. private void ActivateNode( nd )
  135.   nptr  nd;
  136.   {
  137.     register hptr  h, p;
  138.     hptr           *lastp;
  139.     int            first;
  140.  
  141. #ifdef INCDEBUG
  142.     if( nd->nflags & WATCHED )
  143.     lprintf( stdout, "%.1f: Activate %s\n", d2ns(cur_delta), pnode(nd) );
  144. #endif
  145.     if( nd->nflags & STIM )
  146.       {                    /* don't dequeue if ntime == now */
  147.     if( nd->c.event->ntime != cur_delta )
  148.         DequeueEvent( nd );
  149.     nd->nflags &= ~STIM;
  150.     NEXTH( p, nd->curr );
  151.       }
  152.     else
  153.     p = UpdateNode( nd );
  154.  
  155.     (void) EnqueueHist( nd, p, CHECK_PNT );
  156.     nd->nflags |= (ACTIVE_CL | WAS_ACTIVE);
  157.  
  158.     lastp = &(nd->t.punts);
  159.     *lastp = NULL;
  160.     /* look for any pending events as of cur_delta */
  161.     first = TRUE;
  162.     for( p = nd->curr, h = p->next; ; p = h, h = h->next )
  163.       {
  164.     if( h->punt )
  165.       {
  166.         if( PuntTime( h ) < cur_delta )    /* already punted, skip it */
  167.         continue;
  168.  
  169.         if( QPTIME( h ) <= cur_delta )    /* pending: enqueue it */
  170.           {
  171.         if( QPTIME( h ) != cur_delta )    /* cur_delta: do not queue */
  172.             (void) EnqueueHist( nd, h, PUNTED );
  173.         if( DoingFault )
  174.             continue;
  175.         p->next = h->next;        /* and remove it from hist */
  176.         h->next = freeHist;
  177.         freeHist = h;
  178.         h = p;
  179.           }
  180.         else if( first and NotDoingFault )
  181.           {            /* move if punted before next transition */
  182.         p->next = h->next;
  183.         h->next = NULL;
  184.         *lastp = h;
  185.         lastp = &(h->next);
  186.         h = p;
  187.           }
  188.       }
  189.     else
  190.       {
  191.         first = FALSE;
  192.         if( QTIME( h ) < cur_delta )    /* pending: enqueue it */
  193.         (void) EnqueueHist( nd, h, REVAL );
  194.         else
  195.         break;
  196.       }
  197.       }
  198.   }
  199.  
  200.  
  201. /*
  202.  * Define all possible cases due to an event on an active node, as follows:
  203.  *    000 0: no edge, node remains converged (not deviated)
  204.  *    001 1: no edge, node just converged
  205.  *    010 2: no edge, node just deviated
  206.  *    011 3: no edge, node remains deviated
  207.  *    100 4: edge, node remains converged
  208.  *    101 5: edge, node just converged
  209.  *    110 6: edge, node just deviated
  210.  *    111 7: edge, node remains deviated
  211.  */
  212.  
  213. #define    O_DEV        0x1        /* node was previously deviated */
  214. #define    N_DEV        0x2        /* node is now deviated */
  215. #define    EDGE        0x4        /* a transistion ocurred */
  216. #define    CHK        0x8        /* just dequeued a check_pnt event */
  217. #define    SAME_T        0x10        /* event merges at the same time */
  218. #define    N_ACTV        0x20        /* merge events: still active xtors */
  219.  
  220. #define    GetOdev( nd )        ( (nd)->nflags & DEVIATED )
  221.  
  222. private    evptr    dev_evs;        /* deviate events */
  223. private    evptr    mrg_evs;        /* merge events w/transition */
  224. private    evptr    *last_mrg;        /* last merge event w/transition */
  225. private    evptr    mrg0_evs;        /* last merge event */
  226. private    evptr    chk_evs;        /* events with no transition */
  227. private    evptr    inp_evs;        /* input events */
  228. private    evptr    xinp_evs;        /* stop being an input events */
  229. private    evptr    stim_evs;        /* stimulus events */
  230. private    evptr    pend_evs;        /* pending events */
  231.  
  232.  
  233. /*
  234.  * Change the event type to reflect new state, add event to its corresponding
  235.  * event list, set the oldpot field and the DEVIATED bit for the node.
  236.  */
  237. #define    Deviate_Edge( ND, EV, Oval, Chk )        \
  238.   {                            \
  239.     (EV)->type = GetOdev( ND ) | N_DEV | Chk | EDGE;    \
  240.     (EV)->nlink = dev_evs;                \
  241.     dev_evs = (EV);                    \
  242.     (ND)->oldpot = Oval;                \
  243.     (ND)->nflags |= DEVIATED;                \
  244.   }                            \
  245.  
  246.  
  247. #define    Deviate( ND, EV, Oval, Chk )            \
  248.   {                            \
  249.     (EV)->type = GetOdev( ND ) | N_DEV | Chk;        \
  250.     (EV)->nlink = chk_evs;                \
  251.     chk_evs = (EV);                    \
  252.     (ND)->oldpot = Oval;                \
  253.     (ND)->nflags |= DEVIATED;                \
  254.   }                            \
  255.  
  256.  
  257. #define    Deviate_SameVal( EV )                \
  258.   {                            \
  259.     (EV)->type = N_DEV | O_DEV | EDGE;            \
  260.     (EV)->nlink = dev_evs;                \
  261.     dev_evs = (EV);                    \
  262.   }                            \
  263.  
  264.  
  265. /*
  266.  * Change the event type to reflect new state, add event to its corresponding
  267.  * event list and reset the DEVIATED bit.
  268.  */
  269. #define Merge_Edge( ND, EV, Chk )            \
  270.   {                            \
  271.     if( (ND)->nflags & DEVIATED )            \
  272.       {                            \
  273.     (EV)->type = (O_DEV | EDGE | Chk );        \
  274.     *last_mrg = (EV);                \
  275.     last_mrg = & (EV)->nlink;            \
  276.       }                            \
  277.     else                        \
  278.       {                            \
  279.     (EV)->type = (Chk | EDGE);            \
  280.     (EV)->nlink = mrg0_evs;                \
  281.     mrg0_evs = (EV);                \
  282.       }                            \
  283.     (ND)->nflags &= ~DEVIATED;                \
  284.   }                            \
  285.  
  286.  
  287. #define Merge_SameEdge( ND, EV, Chk )            \
  288.   {                            \
  289.     (EV)->type = GetOdev( ND ) | SAME_T | Chk | EDGE;    \
  290.     (EV)->nlink = mrg0_evs;                \
  291.     mrg0_evs = (EV);                    \
  292.     (ND)->nflags &= ~DEVIATED;                \
  293.   }                            \
  294.  
  295.  
  296. #define Merge( ND, EV, Chk )                \
  297.   {                            \
  298.     (EV)->type = GetOdev( ND ) | Chk;            \
  299.     (EV)->nlink = chk_evs;                \
  300.     chk_evs = (EV);                    \
  301.     (ND)->nflags &= ~DEVIATED;                \
  302.   }                            \
  303.  
  304.  
  305. /*
  306.  * Free all punted events currently in nd->t.punts and move all punted events
  307.  * after nd->curr to nd->t.punts. 
  308.  */
  309. private void ReplacePunts( nd )
  310.   nptr  nd;
  311.   {
  312.     register hptr  h, p;
  313.  
  314.     if( DoingFault )
  315.     return;
  316.     h = nd->t.punts;
  317.     if( h != NULL )
  318.       {
  319.     for( p = h; p->next != NULL; p = p->next );
  320.     p->next = freeHist;
  321.     freeHist = h;
  322.       }
  323.     
  324.     h = nd->curr;
  325.     for( p = h; p->next->punt; p = p->next );
  326.     if( p->punt )
  327.       {
  328.     nd->t.punts = h->next;
  329.     h->next = p->next;
  330.     p->next = NULL;
  331.       }
  332.     else
  333.     nd->t.punts = NULL;
  334.   }
  335.  
  336.  
  337. /*
  338.  * Update the state of a node due to a re-evaluation event.
  339.  */
  340. private void UpdateReval( e )
  341.   register evptr  e;
  342.   {
  343.     register nptr   n;            /* node in question */
  344.     register evptr  nxte;        /* next chk_point event (if any) */
  345.     register long   d_t;        /* delta time between events */
  346.  
  347.     n = e->enode;
  348.     nxte = n->c.event;
  349.  
  350.     /* no chk_point event or chk_point is too far in the future */
  351.     if( nxte == NULL or (d_t = nxte->ntime - e->ntime) > INC_RES )
  352.       {
  353.     free_from_node( e, n );
  354.     NewEdge( n, e );
  355.     if( n->nflags & DEVIATED )
  356.       {
  357.         if( n->oldpot == e->eval )
  358.         Merge_Edge( n, e, 0 )
  359.         else
  360.         Deviate_SameVal( e )
  361.       }
  362.     else
  363.         Deviate_Edge( n, e, n->npot, 0 );
  364.     n->npot = e->eval;
  365.       }
  366.     else if( d_t != 0 )
  367.       {
  368.     free_from_node( e, n );
  369.  
  370.     switch( nxte->type )
  371.       {
  372.         case DELAY_CHK :
  373.         ndelaychk_ev++;
  374.         if( nxte->eval == e->eval )
  375.           {
  376.             n->curr = nxte->p.hist;    /* update curr pointer */
  377.             Merge_Edge( n, e, CHK );
  378.             ReplacePunts( n );
  379.           }
  380.         else
  381.           {
  382.             DeleteNextEdge( n );
  383.             NewEdge( n, e );
  384.             Deviate_Edge( n, e, nxte->eval, CHK );
  385.           }
  386.         DequeueEvent( n );
  387.         n->npot = e->eval;
  388.         break;
  389.  
  390.         case DELAY_EV :
  391.         if( nxte->eval == e->eval )
  392.             DelayEvent( e, d_t );        /* delay again */
  393.         else
  394.           {
  395.             lprintf( stdout,
  396.               "Missed Glitch: %s => (%.1f %c) (%.1f %c)\n",
  397.               pnode( n ), d2ns( nxte->p.oldt ), "0XX1"[nxte->eval],
  398.               d2ns( e->ntime ), "0XX1"[e->eval] );
  399.             nxte->type = CHECK_PNT;
  400.             NewEdge( n, e );
  401.             Deviate_Edge( n, e, n->npot, 0 );
  402.             n->npot = e->eval;
  403.           }
  404.         break;
  405.  
  406.         case CHECK_PNT :
  407.         if( n->nflags & DEVIATED )
  408.           {
  409.             if( n->oldpot == e->eval )
  410.             Merge_Edge( n, e, 0 )
  411.             else
  412.             Deviate_SameVal( e )
  413.  
  414.             NewEdge( n, e );
  415.             n->npot = e->eval;
  416.           }
  417.         else if( nxte->eval == e->eval )
  418.           {
  419.             register evptr  ne;
  420.  
  421.             if( (ne = n->events) != NULL )
  422.             while( ne->nlink != NULL )
  423.                 ne = ne->nlink;
  424.  
  425.             if( ne == NULL or ne->ntime > nxte->ntime )
  426.               {
  427.             nxte->p.oldt = e->ntime;
  428.             nxte->type = DELAY_EV;
  429.             DelayEvent( e, d_t );
  430.               }
  431.             else
  432.               {
  433.             NewEdge( n, e );
  434.             Deviate_Edge( n, e, n->npot, 0 );
  435.             n->npot = e->eval;
  436.               }
  437.           }
  438.         else
  439.           {
  440.             NewEdge( n, e );
  441.             Deviate_Edge( n, e, n->npot, 0 );
  442.             n->npot = e->eval;
  443.           }
  444.         break;
  445.  
  446.         case INP_EV :
  447.         case XINP_EV :
  448.         if( n->nflags & DEVIATED )
  449.           {
  450.             if( n->oldpot == e->eval )
  451.             Merge_Edge( n, e, 0 )
  452.             else
  453.             Deviate_SameVal( e );
  454.           }
  455.         else
  456.             Deviate_Edge( n, e, n->npot, 0 );
  457.  
  458.         n->npot = e->eval;
  459.         NewEdge( n, e );
  460.         break;
  461.  
  462.         default :
  463.         lprintf( stderr, "Unexpected Event 0x(%x)\n", nxte->type );
  464.       }
  465.       }
  466.   }
  467.  
  468.  
  469. #define CopyEvent( DST, SRC )        \
  470.   {                    \
  471.     (DST)->p.hist = (SRC)->p.hist;    \
  472.     (DST)->ntime = (SRC)->ntime;    \
  473.     (DST)->rtime = (SRC)->rtime;    \
  474.     (DST)->delay = (SRC)->delay;    \
  475.     (DST)->eval = (SRC)->eval;        \
  476.   }                    \
  477.  
  478.  
  479. private void UpdateCheck_Pnt( e )
  480.   register evptr  e;
  481.   {
  482.     register nptr   n;
  483.     register evptr  nxte;
  484.     register long   d_t;
  485.  
  486.     n = e->enode;
  487.     if( (nxte = n->events) != NULL )
  488.       {
  489.     while( nxte->nlink != NULL )
  490.         nxte = nxte->nlink;
  491.     d_t = nxte->ntime - e->ntime;
  492.       }
  493.  
  494.     if( nxte == NULL or d_t > INC_RES )
  495.       {
  496.     DeleteNextEdge( n );
  497.     if( n->npot == e->eval )
  498.         Merge( n, e, CHK )
  499.     else
  500.         Deviate( n, e, e->eval, CHK );
  501.       }
  502.     else if( d_t == 0 )
  503.       {
  504.     free_from_node( nxte, n );
  505.     if( e->eval == nxte->eval )
  506.       {
  507.         n->curr = e->p.hist;
  508.         if( DoingFault )  n->hchange = *n->curr, n->curr = &n->hchange;
  509.         n->npot = e->eval;
  510.         n->curr->t.r.delay = nxte->delay;
  511.         if( e->rtime == nxte->rtime )
  512.         Merge_SameEdge( n, e, CHK )
  513.         else
  514.           {
  515.         n->curr->t.r.rtime = nxte->rtime;
  516.         Merge_Edge( n, e, CHK );
  517.           }
  518.         ReplacePunts( n );
  519.       }
  520.     else
  521.       {
  522.         DeleteNextEdge( n );
  523.         d_t = e->eval;        /* save old value temporarily */
  524.         CopyEvent( e, nxte );    /* this is the new value! */
  525.         NewEdge( n, e );
  526.         n->npot = e->eval;
  527.         Deviate_Edge( n, e, d_t, CHK );
  528.       }
  529.       }
  530.     else    /* 0 < d_t <= INC_RES */
  531.       {
  532.     if( n->nflags & DEVIATED )
  533.       {
  534.         DeleteNextEdge( n );
  535.         if( n->npot == e->eval )
  536.         Merge( n, e, CHK )
  537.         else
  538.         Deviate( n, e, e->eval, CHK );
  539.       }
  540.     else
  541.       {
  542.         register hptr   h;
  543.  
  544.         NEXTH( h, e->p.hist );
  545.         if( nxte->eval == e->eval and h->time > nxte->ntime )
  546.           {
  547.         e->type = DELAY_CHK;
  548.         DelayEvent( e, d_t );
  549.           }
  550.         else
  551.           {
  552.         DeleteNextEdge( n );
  553.         Deviate( n, e, e->eval, CHK );
  554.           }
  555.       }
  556.       }
  557.   }
  558.  
  559.  
  560. private void UpdateDelay_Chk( e )
  561.   register evptr  e;
  562.   {
  563.     register nptr   n;
  564.     register evptr  nxte;
  565.     register long   d_t;
  566.  
  567.     n = e->enode;
  568.     if( (nxte = n->events) != NULL )
  569.       {
  570.     while( nxte->nlink != NULL )
  571.         nxte = nxte->nlink;
  572.     d_t = nxte->ntime - e->ntime;
  573.       }
  574.  
  575.     if( nxte != NULL and d_t == 0 and nxte->eval == e->eval )
  576.       {
  577.     free_from_node( nxte, n );
  578.     n->curr = e->p.hist;
  579.     n->curr->t.r.delay = nxte->delay;
  580.     if( e->rtime == nxte->rtime )
  581.         Merge_SameEdge( n, e, CHK )
  582.     else
  583.       {
  584.         n->curr->t.r.rtime = nxte->rtime;
  585.         Merge_Edge( n, e, CHK );
  586.       }
  587.     n->npot = e->eval;
  588.     ReplacePunts( n );
  589.       }
  590.     else    /* event got punted (and maybe something else was queued) */
  591.       {
  592.     DeleteNextEdge( n );
  593.     if( nxte != NULL and d_t == 0 )
  594.       {
  595.         free_from_node( nxte, n );
  596.         d_t = e->eval;
  597.         CopyEvent( e, nxte );
  598.         Deviate_Edge( n, e, d_t, CHK );
  599.         NewEdge( n, e );
  600.         n->npot = e->eval;
  601.       }
  602.     else                    /* nothing else was queued */
  603.         Deviate( n, e, e->eval, CHK );
  604.       }
  605.   }
  606.  
  607.  
  608. private void UpdateDelay_Ev( e )
  609.   register evptr  e;
  610.   {
  611.     register nptr   n;
  612.     register evptr  nxte;
  613.     register long   d_t;
  614.  
  615.     n = e->enode;
  616.     if( (nxte = n->events) != NULL )
  617.       {
  618.     while( nxte->nlink != NULL )
  619.         nxte = nxte->nlink;
  620.     d_t = nxte->ntime - e->ntime;
  621.       }
  622.  
  623.     if( nxte != NULL and d_t == 0 and nxte->eval == e->eval )
  624.       {
  625.     register hptr   h;
  626.  
  627.     free_from_node( nxte, n );
  628.     NEXTH( h, n->curr );
  629.     n->curr = h;
  630.     Merge_SameEdge( n, e, CHK );
  631.     n->npot = e->eval;
  632.     ReplacePunts( n );
  633.       }
  634.     else        /* expected event was punted */
  635.       {
  636.     lprintf( stdout, "Missed Glitch: %s => (%.1f %c) -> (~%.1f %c)\n",
  637.       pnode( n ), d2ns( e->p.oldt ), "0XX1"[e->eval],
  638.       d2ns( (e->ntime + e->p.oldt)/2 ), "0XX1"[n->npot] );
  639.  
  640.     DeleteNextEdge( n );
  641.     if( nxte != NULL and d_t == 0 )
  642.       {
  643.         free_from_node( nxte, n );
  644.         NewEdge( n, nxte );
  645.         d_t = e->eval;
  646.         CopyEvent( e, nxte );
  647.         Deviate_Edge( n, e, d_t, CHK );
  648.         n->npot = e->eval;
  649.       }
  650.     else
  651.         Deviate( n, e, e->eval, CHK );
  652.       }
  653.   }
  654.  
  655.  
  656. private void update_nodes( e )
  657.   evptr  e;
  658.   {
  659.     nptr   n;
  660.     int    hgmi;
  661.  
  662.     /* clear event lists */
  663.  
  664.     dev_evs = chk_evs = mrg_evs = mrg0_evs = inp_evs = xinp_evs =
  665.     stim_evs = pend_evs = NULL;
  666.     last_mrg = &mrg_evs;
  667.  
  668.     do
  669.       {
  670. #ifdef STATS
  671.     { extern int ev_hgm; if( ev_hgm ) IncHistEvCnt( (Uint) e->type ); }
  672. #endif STATS
  673.     switch( e->type )
  674.       {
  675.         case PUNTED :
  676.         npunted_ev++;
  677.         UpdateReval( e );
  678.         break;
  679.  
  680.         case REVAL :
  681.         case DECAY_EV :
  682.         nreval_ev++;
  683.         UpdateReval( e );
  684.         break;
  685.  
  686.         case DELAY_CHK :
  687.         ndelaychk_ev++;
  688.         UpdateDelay_Chk( e );
  689.         break;
  690.  
  691.         case DELAY_EV :
  692.         ndelay_ev++;
  693.         UpdateDelay_Ev( e );
  694.         break;
  695.  
  696.         case CHECK_PNT :
  697.         ncheckpt_ev++;
  698.         UpdateCheck_Pnt( e );
  699.         break;
  700.  
  701.         case XINP_EV :
  702.         ncheckpt_ev++;
  703.         n = e->enode;
  704.         n->curr = e->p.hist;
  705.         n->nflags &= ~(INPUT | ACTIVE_CL);
  706.         e->nlink = xinp_evs;
  707.         xinp_evs = e;
  708.         ReplacePunts( n );
  709.         break;
  710.  
  711.         case INP_EV :
  712.         ncheckpt_ev++;
  713.         n = e->enode;
  714.         while( n->events and n->events->ntime != cur_delta )
  715.             free_event( n->events );
  716.         ReplacePunts( n );
  717.         n->curr = e->p.hist;
  718.         n->npot = e->eval;
  719.         n->nflags |= INPUT;
  720.         n->nflags &= ~DEVIATED;
  721.         e->nlink = inp_evs;
  722.         inp_evs = e;
  723.         break;
  724.  
  725.         case STIM_INP :
  726.         nstimuli_ev++;
  727.         n = e->enode;
  728.         n->npot = e->eval;
  729.         n->curr = e->p.hist;
  730.         n->nflags |= INPUT;
  731.         e->nlink = stim_evs;
  732.         stim_evs = e;
  733.         break;
  734.  
  735.         case STIM_XINP :
  736.           {
  737.         register hptr  h;
  738.  
  739.         nstimuli_ev++;
  740.         n = e->enode;
  741.         n->curr = e->p.hist;
  742.         n->nflags &= ~INPUT;
  743.         NEXTH( h, n->curr );
  744.         if( not EnqueueHist( n, h, STIMULI ) )
  745.             n->nflags &= ~STIM;
  746.         break;
  747.           }
  748.  
  749.         case STIMULI :
  750.         nstimuli_ev++;
  751.         n = e->enode;
  752.         n->npot = e->eval;
  753.         n->curr = e->p.hist;
  754.         e->nlink = stim_evs;
  755.         stim_evs = e;
  756.         break;
  757.  
  758.         case PENDING :
  759.         e->nlink = pend_evs;
  760.         pend_evs = e;
  761.         break;
  762. #ifdef notdef
  763.         case PUNTED :
  764.         npunted_ev++;
  765.         n = e->enode;
  766.             /* else: punt along with chk_pnt, the later handles it */
  767.         if( n->c.event == NULL or n->c.event->ntime != e->ntime )
  768.           {
  769.             int  oval;
  770.  
  771.             free_from_node( e, n );
  772.             NewEdge( n, e );
  773.             oval = (n->nflags & DEVIATED) ? n->oldpot : n->npot;
  774.             Deviate_Edge( n, e, oval, 0 );
  775.             n->npot = e->eval;
  776.           }
  777.         break;
  778. #endif
  779.         case CHNG_MODEL :
  780.         curr_model = model_table[ modelp->val ];
  781.         modelp = modelp->next;
  782.         if( modelp != NULL )
  783.             (void) EnqueueOther( CHNG_MODEL, (long) modelp->time );
  784.         break;
  785.  
  786. #ifdef FAULT_SIM
  787.         case TRIGGER_EV :
  788.         stop_early = do_trigger( e );
  789.         break;
  790. #endif
  791.         default:
  792.         lprintf( stderr,
  793.           "update_nodes: bad event (%x) @ delta=%d for node %s\n",
  794.            e->type, cur_delta, pnode( e->enode ) );
  795.       }
  796.     npending -= 1;
  797.       }
  798.     while( (e = e->flink) != NULL );
  799.  
  800.     *last_mrg = mrg0_evs;    /* join the 2 lists, order is important */
  801.   }
  802.  
  803.  
  804. /*
  805.  * Run through the various event lists and update the state of all transistors
  806.  * controlled by the node that triggered the event.  Also mark all nodes that
  807.  * need to be considered for evaluation as VISITED, this doesn't imply they
  808.  * will be evaluated.
  809.  */
  810. private void UpdateTransistors()
  811.   {
  812.     register evptr  e;
  813.     register lptr   l;
  814.     register tptr   t;
  815.  
  816.     for( e = dev_evs; e != NULL; e = e->nlink )
  817.       {
  818.     if( (e->type & O_DEV) == 0 )        /* just deviated */
  819.       {
  820.         for( l = e->enode->ngate; l != NULL; l = l->next )
  821.           {
  822.         t = l->xtor;
  823.             if( t->tflags & ACTIVE_T )
  824.             t->state = compute_trans_state( t );
  825.         t->source->nflags |= VISITED;    /* always mark src/drn */
  826.         t->drain->nflags |= VISITED;
  827.           }
  828.       }
  829.     else                    /* was already deviated */
  830.       {
  831.         for( l = e->enode->ngate; l != NULL; l = l->next )
  832.           {
  833.         t = l->xtor;
  834.         if( t->tflags & ACTIVE_T )
  835.           {
  836.             t->state = compute_trans_state( t );
  837.             t->source->nflags |= VISITED;
  838.             t->drain->nflags |= VISITED;
  839.           }
  840.           }
  841.       }
  842.       }
  843.  
  844.     for( e = mrg_evs; e != NULL; e = e->nlink )
  845.       {
  846.     for( l = e->enode->ngate; l != NULL; l = l->next )
  847.       {
  848.         t = l->xtor;
  849.         if( t->tflags & ACTIVE_T )
  850.           {
  851.         t->state = compute_trans_state( t );
  852.         t->source->nflags |= VISITED;
  853.         t->drain->nflags |= VISITED;
  854.           }
  855.       }
  856.       }
  857.  
  858.     for( e = chk_evs; e != NULL; e = e->nlink )
  859.       {
  860.     if( (e->type & (N_DEV | O_DEV) ) == N_DEV )    /* just deviated */
  861.       {
  862.         for( l = e->enode->ngate; l != NULL; l = l->next )
  863.           {
  864.         t = l->xtor;
  865.             if( t->tflags & ACTIVE_T )
  866.             t->state = compute_trans_state( t );
  867.         t->source->nflags |= VISITED;    /* always mark src/drn */
  868.         t->drain->nflags |= VISITED;
  869.           }
  870.       }
  871.       }
  872.  
  873.     for( e = inp_evs; e != NULL; e = e->nlink )
  874.       {
  875.     for( l = e->enode->ngate; l != NULL; l = l->next )
  876.       {
  877.         t = l->xtor;
  878.         if( t->tflags & ACTIVE_T )
  879.           {
  880.         t->state = compute_trans_state( t );
  881.         t->source->nflags |= VISITED;
  882.         t->drain->nflags |= VISITED;
  883.           }
  884.       }
  885.       }
  886.  
  887.     for( e = xinp_evs; e != NULL; e = e->nlink )
  888.     e->enode->nflags |= VISITED;
  889.  
  890.     for( e = stim_evs; e != NULL; e = e->nlink )
  891.       {
  892.     for( l = e->enode->ngate; l != NULL; l = l->next )
  893.       {
  894.         t = l->xtor;
  895.         if( t->tflags & ACTIVE_T )
  896.           {
  897.         t->state = compute_trans_state( t );
  898.         t->source->nflags |= VISITED;
  899.         t->drain->nflags |= VISITED;
  900.           }
  901.       }
  902.       }
  903.  
  904.     VDD_node->nflags &= ~VISITED;
  905.     GND_node->nflags &= ~VISITED;
  906.   }
  907.  
  908.  
  909. #define hash_terms( T )         ( (Ulong)((T)->source) ^ (Ulong)((T)->drain) )
  910.  
  911.  
  912. /*
  913.  * Build the connection list for node 'n'.  Determine (1) if all nodes in the
  914.  * list are converged or whether this list is adjacent to a transistor whose
  915.  * gate is deviated, (2) if there are any inactive nodes (or transistors) in
  916.  * the connection list, and (3) whether any inputs (transistor gates) to the
  917.  * connection list have a transition at the current time.  As a side effect
  918.  * set the 'withdriven' flag.  The algorithm to construct the connection list
  919.  * is the same as that used by BuildConnList.
  920.  *
  921.  * We must be careful not to report as an input transition nodes that stop
  922.  * being inputs (i.e. hist->delay == 0 and hist->inp == 0).
  923.  */
  924. #define IsCurrTransition( H )            \
  925.   ( (H)->time == cur_delta and ((H)->inp == 1 or (H)->t.r.delay != 0) )
  926.  
  927. private pstg GetConnList( n )
  928.   register nptr  n;
  929.   {
  930.     register nptr  next, this, other, *inext;
  931.     register lptr  l;
  932.     register tptr  t;
  933.     register hptr  h;
  934.     register int   status;
  935.     int            n_par = 0;
  936.     static Stage   stage;
  937.  
  938.     stage.nd_list = n;
  939.     stage.inp_list = NULL;
  940.  
  941.     status = ALL_MERGED;
  942.     withdriven = FALSE;
  943.  
  944.     n->nflags &= ~VISITED;
  945.     inext = &(stage.inp_list);
  946.  
  947.     if( NeedUpdate( n ) )
  948.     (void) UpdateNode( n );
  949.     if( IsDeviated( n ) )
  950.     status &= ~ALL_MERGED;
  951.  
  952.     if( n->nflags & INPUT )
  953.       {
  954.     stage.flags = ALL_MERGED | ONLY_INPUT;
  955.     return( &stage );
  956.       }
  957.  
  958.     next = this = n->nlink = n;
  959.     do
  960.       {
  961.     for( l = this->nterm; l != NULL; l = l->next )
  962.       {
  963.         t = l->xtor;
  964.         if( not (t->tflags & ACTIVE_T) )
  965.           {
  966.         if( t->ttype & GATELIST )
  967.           {
  968.             for( t = (tptr) t->gate; t != NULL; t = t->scache.t )
  969.             if( NeedUpdate( t->gate ) )
  970.                 (void) UpdateNode( t->gate );
  971.             t = l->xtor;
  972.           }
  973.         else if( NeedUpdate( t->gate ) )
  974.             (void) UpdateNode( t->gate );
  975.  
  976.         t->state = compute_trans_state( t );
  977.           }
  978.         else if( status & ALL_MERGED )
  979.           {
  980.         if( t->ttype & GATELIST )
  981.           {
  982.             for( t = (tptr) t->gate; t != NULL; t = t->scache.t )
  983.             if( t->gate->nflags & DEVIATED )
  984.               {
  985.                 status &= ~ALL_MERGED;
  986.                 break;
  987.               }
  988.             t = l->xtor;
  989.           }
  990.         else if( t->gate->nflags & DEVIATED )
  991.             status &= ~ALL_MERGED;
  992.           }
  993.  
  994.         if( t->state == OFF )
  995.         continue;
  996.  
  997.         if( t->tflags & CROSSED )
  998.           {
  999.         t->tflags &= ~CROSSED;
  1000.         continue;
  1001.           }
  1002.  
  1003.         t->scache.r = t->dcache.r = NULL;
  1004.  
  1005.         other = other_node( t, this );
  1006.  
  1007.         if( NeedUpdate( other ) )
  1008.         (void) UpdateNode( other );
  1009.         if( IsDeviated( other ) )
  1010.         status &= ~ALL_MERGED;
  1011.  
  1012.         if( other->nflags & INPUT )
  1013.           {
  1014.         withdriven = TRUE;
  1015.         if( other->nlink == NULL and 
  1016.           not (other->nflags & (ACTIVE_CL | POWER_RAIL)) )
  1017.           {
  1018.             *inext = other;
  1019.             inext = &(other->nlink);
  1020.             *inext = other;        /* anything other than NULL */
  1021.           }
  1022.           }
  1023.         else
  1024.           {
  1025.         t->tflags |= CROSSED;
  1026.         if( other->nlink == NULL )
  1027.           {
  1028.             other->nflags &= ~VISITED;
  1029.             other->nlink = n;
  1030.             next->nlink = other;
  1031.             next = other;
  1032.             other->n.tran = t;
  1033.           }
  1034.         else if( model_num != LIN_MODEL )
  1035.             goto is_trans;
  1036.         else if( hash_terms( other->n.tran ) == hash_terms( t ) )
  1037.           {
  1038.             register tptr  tran = other->n.tran;
  1039.  
  1040.             if( tran->tflags & PARALLEL )
  1041.             t->dcache.t = par_list( tran );
  1042.             else
  1043.               {
  1044.             if( n_par >= MAX_PARALLEL )
  1045.               {
  1046.                 WarnTooManyParallel();
  1047.                 t->tflags |= PBROKEN;
  1048.                 continue;
  1049.               }
  1050.             tran->n_par = n_par++;
  1051.             tran->tflags |= PARALLEL;
  1052.               }
  1053.             par_list( tran ) = t;
  1054.             t->tflags |= PBROKEN;
  1055.           }
  1056.         else
  1057.           {
  1058.             t->tflags |= BROKEN;
  1059.             continue;
  1060.           }
  1061.           }
  1062.     is_trans :
  1063.         if( t->ttype & GATELIST )
  1064.           {
  1065.         for( t = (tptr) t->gate; t; t = t->scache.t )
  1066.           {
  1067.             h = t->gate->curr;
  1068.             if( IsCurrTransition( h ) )
  1069.               {
  1070.             t = l->xtor;
  1071.             status |= INP_TRANS;
  1072.             break;
  1073.               }
  1074.           }
  1075.         t = l->xtor;
  1076.           }
  1077.         else
  1078.           {
  1079.         h = t->gate->curr;
  1080.         if( IsCurrTransition( h ) )
  1081.             status |= INP_TRANS;
  1082.           }
  1083.       }        /* end of for each nterm */
  1084.       }
  1085.     while( (this = this->nlink) != n );
  1086.  
  1087.     next->nlink = NULL;
  1088.     *inext = NULL;
  1089.     stage.flags = status;
  1090.  
  1091.     return( &stage );
  1092.   }
  1093.  
  1094.  
  1095. /*
  1096.  * Activate the gate of a transistor to act as stimuli.  First check
  1097.  * that the node in question is not part of an active cluster or is
  1098.  * already acting as stimuli.
  1099.  */
  1100. #define    StimulateGate( GATE )                \
  1101.   {                            \
  1102.     if( NeedUpdate( GATE ) )                \
  1103.       {                            \
  1104.     register hptr nextH = UpdateNode( GATE );    \
  1105.     if( EnqueueHist( GATE, nextH, STIMULI ) )    \
  1106.         (GATE)->nflags |= STIM;            \
  1107.       }                            \
  1108.   }
  1109.  
  1110.  
  1111. /*
  1112.  * Activate all nodes and transistors in the connection list of node 'nd',
  1113.  * scheduling pending events on the outputs and activating any inputs as
  1114.  * stimuli.  This routine assumes that the connection list has already been
  1115.  * built GetConnList.  Also activate all INPUT nodes connected to the stage.
  1116.  * The routine returns TRUE if any of the nodes in the connection list has
  1117.  * any pending punted events, else FALSE;
  1118.  */
  1119. private void ActivateStage( stg )
  1120.   pstg  stg;
  1121.   {
  1122.     register nptr  n;
  1123.  
  1124.     n = stg->nd_list;
  1125.     do
  1126.       {
  1127.     register lptr  l;
  1128.     register tptr  t;
  1129.  
  1130.     if( not (n->nflags & ACTIVE_CL) )
  1131.         ActivateNode( n );
  1132.  
  1133.     for( l = n->nterm; l != NULL; l = l->next )
  1134.       {
  1135.         t = l->xtor;
  1136.         if( t->tflags & ACTIVE_T )
  1137.         continue;
  1138.         t->tflags |= ACTIVE_T;
  1139.         if( t->ttype & GATELIST )
  1140.           {
  1141.         for( t = (tptr) t->gate; t != NULL; t = t->scache.t )
  1142.             StimulateGate( t->gate );
  1143.           }
  1144.         else
  1145.         StimulateGate( t->gate );
  1146.       }
  1147.       }
  1148.     while( (n = n->nlink) != NULL );
  1149.  
  1150.     n = stg->inp_list;        /* traverse inputs connected to stage */
  1151.     while( n != NULL )
  1152.       {
  1153.     register nptr  next;
  1154.  
  1155.     if( not (n->nflags & (ACTIVE_CL | POWER_RAIL)) )
  1156.         (void) ActivateNode( n );
  1157.  
  1158.     next = n->nlink;
  1159.     n->nlink = NULL;
  1160.     n = next;
  1161.       }
  1162.   }
  1163.  
  1164.  
  1165. /*
  1166.  * Merge any 'future' punted events from previous runs with the current
  1167.  * history for the node.  Note that events created prior to cur_delta are
  1168.  * simply discarded (if they belong in the history the should have been
  1169.  * recreated and re-punted).
  1170.  */
  1171. private void MergePunts( nd )
  1172.   nptr  nd;
  1173.   {
  1174.     register hptr  h, p, nx;
  1175.  
  1176.     /* skip past any punted events already in the history */
  1177.     for( nx = nd->curr; nx->next->punt; nx = nx->next );
  1178.  
  1179.     p = nd->t.punts;
  1180.     do
  1181.       {
  1182.     h = p;
  1183.     p = p->next;
  1184.     if( QPTIME( h ) < cur_delta )        /* in the past, free it */
  1185.       {
  1186.         h->next = freeHist;
  1187.         freeHist = h;
  1188.       }
  1189.     else                    /* in the future, merge */
  1190.       {
  1191.         h->next = nx->next;
  1192.         nx->next = h;
  1193.         nx = h;
  1194.       }
  1195.       }
  1196.     while( p != NULL );
  1197.  
  1198.     nd->t.punts = NULL;
  1199.   }
  1200.  
  1201.  
  1202. /*
  1203.  * Deactivate all nodes on the connection list and destroy the list.  If a
  1204.  * node has any gate connections then turn it into a stimulus node.  Also
  1205.  * deactivate any non-OFF transistor on the connection list and move any
  1206.  * punted events from the previous simulation that have yet to be enqueued
  1207.  * back into the history.  We can't deactivate OFF transistors because some
  1208.  * of them may be boundary transistors.
  1209.  * For all transistors in the stage, clear the src/drn caches and any flags
  1210.  * that may have been set when building stage.
  1211.  */
  1212. private void DeactivateStage( stg, skipnd )
  1213.   pstg  stg;
  1214.   nptr  skipnd;
  1215.   {
  1216.     register nptr  n, next;
  1217.  
  1218.     for( n = stg->nd_list; n != NULL; n = next )
  1219.       {
  1220.     register lptr  l;
  1221.     register tptr  t;
  1222.  
  1223.     next = n->nlink;
  1224.     n->nlink = NULL;
  1225.  
  1226. #ifdef INCDEBUG
  1227.     if( n->nflags & WATCHED )
  1228.         lprintf(stdout, "%.1f: Deactivate %s\n",d2ns(cur_delta),pnode(n));
  1229. #endif
  1230.     if( n->nflags & ACTIVE_CL )
  1231.       {
  1232.         if( n->c.event != NULL and n->c.event->ntime > cur_delta )
  1233.         DequeueEvent( n );
  1234.         n->nflags &= ~ACTIVE_CL;
  1235.         if( n->t.punts != NULL )
  1236.         MergePunts( n );
  1237.       }
  1238.     if( n->ngate != NULL and not (n->nflags & STIM) and n != skipnd )
  1239.       {
  1240.         hptr  h;
  1241.         NEXTH( h, n->curr );
  1242.         if( EnqueueHist( n, h, STIMULI ) )
  1243.         n->nflags |= STIM;
  1244.       }
  1245.  
  1246.     for( l = n->nterm; l != NULL; l = l->next )
  1247.       {
  1248.         t = l->xtor;
  1249.         t->dcache.r = NULL;        /* may be set for parallel xtors */
  1250.  
  1251.         if( (t->tflags & ACTIVE_T) and (t->state != OFF or
  1252.           (other_node( t, n )->nflags & INPUT))  )
  1253.         t->tflags = 0;
  1254.         else
  1255.         t->tflags &= ~(BROKEN | PBROKEN | PARALLEL);
  1256.       }
  1257.       }
  1258.  
  1259.     for( n = stg->inp_list; n != NULL; n = next )
  1260.       {
  1261.     next = n->nlink;
  1262.     n->nlink = NULL;
  1263.       }
  1264.   }
  1265.  
  1266.  
  1267.  
  1268. private void UndoStage( stg )
  1269.   pstg  stg;
  1270.   {
  1271.     register nptr  n, next;
  1272.     register lptr  l;
  1273.     register tptr  t;
  1274.  
  1275.     for( n = stg->nd_list; n != NULL; n = next )
  1276.       {
  1277.     next = n->nlink;
  1278.     n->nlink = NULL;
  1279.  
  1280.     for( l = n->nterm; l != NULL; l = l->next )
  1281.       {
  1282.         t = l->xtor;
  1283.         t->dcache.r = NULL;
  1284.         t->tflags &= ~(BROKEN | PBROKEN | PARALLEL);
  1285.       }
  1286.       }
  1287.  
  1288.     for( n = stg->inp_list; n != NULL; n = next )
  1289.       {
  1290.     next = n->nlink;
  1291.     n->nlink = NULL;
  1292.       }
  1293.   }
  1294.  
  1295.  
  1296. /*
  1297.  * Evaluate the source/drain of all active transistors controlled by 'nd'.
  1298.  * Activate/Deactivate clusters as required.  Return TRUE if there are any
  1299.  * active transistors controlled by this node, FALSE otherwise.
  1300.  * If force is TRUE then evaluate even if all nodes in the clusters are
  1301.  * merged.
  1302.  */
  1303. private int EvalSrcDrn( nd, force )
  1304.   nptr    nd;
  1305.   int     force;
  1306.   {
  1307.     register lptr  l;
  1308.     register int   found;
  1309.     register nptr  nterm;
  1310.     pstg           stg;
  1311.  
  1312.     found = FALSE;
  1313.     cur_node = nd;
  1314.     for( l = nd->ngate; l != NULL; l = l->next )
  1315.       {
  1316.     tptr  t = l->xtor;
  1317.  
  1318.     if( not( t->tflags & ACTIVE_T ) )
  1319.         continue;
  1320.  
  1321.     found = TRUE;
  1322.     nterm = t->source;
  1323.     if( nterm->nflags & VISITED )
  1324.       {
  1325.         stg = GetConnList( nterm );
  1326.         if( stg->flags & ONLY_INPUT )
  1327.           {
  1328.         if( not (nterm->nflags & (ACTIVE_CL | POWER_RAIL)) and 
  1329.           nd->nflags & DEVIATED )
  1330.             (void) ActivateNode( nterm );
  1331.           }
  1332.         else if( (stg->flags & ALL_MERGED) and not force )
  1333.         DeactivateStage( stg, (nptr) NULL );
  1334.         else
  1335.           {
  1336.         ActivateStage( stg );
  1337.         (*curr_model)( nterm );
  1338.           }
  1339.       }
  1340.  
  1341.     nterm = t->drain;
  1342.     if( nterm->nflags & VISITED )
  1343.       {
  1344.         stg = GetConnList( nterm );
  1345.         if( stg->flags & ONLY_INPUT )
  1346.           {
  1347.         if( not (nterm->nflags & (ACTIVE_CL | POWER_RAIL)) and 
  1348.           nd->nflags & DEVIATED )
  1349.             ActivateNode( nterm );
  1350.           }
  1351.         else if( (stg->flags & ALL_MERGED) and not force )
  1352.         DeactivateStage( stg, (nptr) NULL );
  1353.         else
  1354.           {
  1355.         ActivateStage( stg );
  1356.         (*curr_model)( nterm );
  1357.           }
  1358.       }
  1359.       }
  1360.     return( found );
  1361.   }
  1362.  
  1363.  
  1364. /*
  1365.  * Evaluate the source/drain of ALL transistors controlled by 'nd', which just
  1366.  * deviated.  Different things should be done if a transition caused the node
  1367.  * to deviate or a lack of transition.
  1368.  */
  1369. private void EvalJustDeviated( nd, has_trans )
  1370.   nptr  nd;
  1371.   int   has_trans;
  1372.   {
  1373.     pstg  stg;
  1374.     lptr  l;
  1375.  
  1376.     cur_node = nd;
  1377.     for( l = nd->ngate; l != NULL; l = l->next )
  1378.       {
  1379.     register nptr  nterm;
  1380.     register tptr  t;
  1381.  
  1382.     t = l->xtor;
  1383.     nterm = t->source;
  1384.     if( nterm->nflags & VISITED )
  1385.       {
  1386.         stg = GetConnList( nterm );
  1387.         if( stg->flags & ONLY_INPUT )
  1388.           {
  1389.         if( not (nterm->nflags & (ACTIVE_CL | POWER_RAIL)) )
  1390.             ActivateNode( nterm );
  1391.           }
  1392.         else
  1393.           {
  1394.         ActivateStage( stg );
  1395.         if( has_trans or (stg->flags & INP_TRANS) )
  1396.             (*curr_model)( nterm );
  1397.         else
  1398.             UndoStage( stg );
  1399.           }
  1400.       }
  1401.  
  1402.     nterm = t->drain;
  1403.     if( nterm->nflags & VISITED )
  1404.       {
  1405.         stg = GetConnList( nterm );
  1406.         if( stg->flags & ONLY_INPUT )
  1407.           {
  1408.         if( not (nterm->nflags & (ACTIVE_CL | POWER_RAIL)) )
  1409.             ActivateNode( nterm );
  1410.           }
  1411.         else
  1412.           {
  1413.         ActivateStage( stg );
  1414.         if( has_trans or (stg->flags & INP_TRANS) )
  1415.             (*curr_model)( nterm );
  1416.         else
  1417.             UndoStage( stg );
  1418.           }
  1419.       }
  1420.                 /* may happen if src/drn are inputs now */
  1421.     if( not (t->tflags & ACTIVE_T) )
  1422.       {
  1423.         t->tflags |= ACTIVE_T;
  1424.         if( t->ttype & GATELIST )
  1425.           {
  1426.         for( t = (tptr) t->gate; t != NULL; t = t->scache.t )
  1427.             StimulateGate( t->gate );
  1428.         t = l->xtor;
  1429.           }
  1430.         t->state = compute_trans_state( t );
  1431.       }
  1432.       }
  1433.   }
  1434.  
  1435.  
  1436. private void EvalInputs()
  1437.   {
  1438.     register evptr  ev;
  1439.     register nptr   n;
  1440.  
  1441.     for( ev = inp_evs; ev != NULL; ev = ev->nlink )
  1442.       {
  1443.     register nptr   other;
  1444.     register lptr   l;
  1445.     register tptr   t;
  1446.     int             act_tran = FALSE;
  1447.  
  1448.     n = cur_node = ev->enode;
  1449.     n->nflags &= ~ACTIVE_CL;    /* assume it won't be active */
  1450.  
  1451.     for( l = n->nterm; l != NULL; l = l->next )
  1452.       {
  1453.         pstg  stg;
  1454.  
  1455.         t = l->xtor;
  1456.         other = other_node( t, n );
  1457.         stg = GetConnList( other );
  1458.         if( stg->flags & ALL_MERGED )
  1459.           {
  1460.         if( not (stg->flags & ONLY_INPUT) )
  1461.             DeactivateStage( stg, (nptr) NULL );
  1462.         else if( t->tflags & ACTIVE_T )
  1463.             act_tran = TRUE;
  1464.           }
  1465.         else
  1466.           {
  1467.         ActivateStage( stg );
  1468.         (*curr_model)( other );
  1469.           }
  1470.       }
  1471.     if( act_tran == TRUE and not (n->nflags & (POWER_RAIL | ACTIVE_CL)) )
  1472.       {
  1473.         register hptr  h;
  1474.  
  1475.         NEXTH( h, n->curr );
  1476.         if( EnqueueHist( n, h, CHECK_PNT ) )
  1477.         n->nflags |= ACTIVE_CL;
  1478.       }
  1479.       }
  1480.  
  1481.     for( ev = inp_evs; ev != NULL; ev = ev->nlink )
  1482.       {
  1483.     int   n_active;
  1484.  
  1485.     n = cur_node = ev->enode;
  1486.     n_active = EvalSrcDrn( n, FALSE );
  1487.  
  1488.     /* 
  1489.      * if node is not active anymore and it controls any 
  1490.      * active transistors turn it into a stimulus node
  1491.      */
  1492.     if( n_active == TRUE and not (n->nflags & ACTIVE_CL) )
  1493.       {
  1494.         register hptr  h;
  1495.  
  1496.         NEXTH( h, n->curr );
  1497.         if( EnqueueHist( n, h, STIMULI ) )
  1498.         n->nflags |= STIM;
  1499.       }
  1500.       }
  1501.   }
  1502.  
  1503.  
  1504. private void EvalStimulus()
  1505.   {
  1506.     evptr  ev;
  1507.     int    n_active;
  1508.     nptr   nd;
  1509.  
  1510.     for( ev = stim_evs; ev != NULL; ev = ev->nlink )
  1511.       {
  1512.     nd = ev->enode;
  1513.     n_active = EvalSrcDrn( nd, FALSE );
  1514.  
  1515.     if( not n_active )            /* no active transistors */
  1516.         nd->nflags &= ~STIM;
  1517.     else if( nd->nflags & STIM )        /* enqueue next transition */
  1518.       {
  1519.         register hptr  h;
  1520.  
  1521.         NEXTH( h, nd->curr );
  1522.         if( not EnqueueHist( nd, h, STIMULI ) )
  1523.         nd->nflags &= ~STIM;
  1524.       }
  1525.       }
  1526.   }
  1527.  
  1528.  
  1529. private void EvalXinputs()
  1530.   {
  1531.     register evptr  ev;
  1532.     register nptr   n;
  1533.     pstg            stg;
  1534.  
  1535.     for( ev = xinp_evs; ev != NULL; ev = ev->nlink )
  1536.       {
  1537.     n = cur_node = ev->enode;
  1538.     if( n->nflags & VISITED )
  1539.       {
  1540.         stg = GetConnList( n );
  1541.         if( stg->flags & ALL_MERGED )
  1542.         DeactivateStage( stg, (nptr) NULL );
  1543.         else
  1544.           {
  1545.         ActivateStage( stg );
  1546.         (*curr_model)( n );
  1547.           }
  1548.       }
  1549.       }
  1550.   }
  1551.  
  1552.  
  1553. private void EvalEventList()
  1554.   {
  1555.     register evptr  e;
  1556.     register nptr   n;
  1557.     int             status;
  1558.     pstg            stg;
  1559.     
  1560.     for( e = dev_evs; e != NULL; e = e->nlink )
  1561.       {
  1562.     n = e->enode;
  1563.     if( (e->type & O_DEV) == 0 )
  1564.         EvalJustDeviated( n, TRUE );
  1565.     else
  1566.         (void) EvalSrcDrn( n, FALSE );
  1567.  
  1568.       /* if the node is still active schedule its next CHECK_PNT event */
  1569.     if( (n->nflags & ACTIVE_CL) and (e->type & CHK) )
  1570.       {
  1571.         hptr  h;
  1572.  
  1573.         NEXTH( h, n->curr );
  1574.         (void) EnqueueHist( n, h, CHECK_PNT );
  1575.       }
  1576.       }
  1577.  
  1578.     for( e = mrg_evs; e != NULL; e = e->nlink )
  1579.       {
  1580.     status = ( (e->type & (SAME_T | O_DEV)) == O_DEV ) ? TRUE : FALSE;
  1581.         
  1582.     if( EvalSrcDrn( e->enode, status ) )
  1583.         e->type |= N_ACTV;
  1584.       }
  1585.  
  1586.     for( e = mrg_evs; e != NULL; e = e->nlink )
  1587.       {
  1588.     n = e->enode;
  1589.     stg = GetConnList( n );
  1590.     if( stg->flags & ALL_MERGED )
  1591.         DeactivateStage( stg, (e->type & N_ACTV) ? (nptr) NULL : n );
  1592.     else
  1593.         UndoStage( stg );
  1594.  
  1595.     if( (n->nflags & ACTIVE_CL) and (e->type & CHK) )
  1596.       {
  1597.         hptr  h;
  1598.  
  1599.         NEXTH( h, n->curr );
  1600.         (void) EnqueueHist( n, h, CHECK_PNT );
  1601.       }
  1602.       }
  1603.  
  1604.     for( e = chk_evs; e != NULL; e = e->nlink )
  1605.       {
  1606.     n = e->enode;
  1607.     switch( e->type & (EDGE| O_DEV | N_DEV) )
  1608.       {
  1609.         case 0 :
  1610.         lprintf( stderr, "warning: case 0 time=%.1f for %s\n",
  1611.           d2ns( cur_delta ), pnode( n ) );
  1612.         break;
  1613.  
  1614.         case O_DEV :    /* Node just merged but no transition */
  1615.         stg = GetConnList( n );
  1616.         if( stg->flags & ALL_MERGED )
  1617.             DeactivateStage( stg, (nptr) NULL );
  1618.         else
  1619.             UndoStage( stg );
  1620.         break;
  1621.  
  1622.         case N_DEV :    /* Node just deviated but no transition */
  1623.         n = e->enode;
  1624.         EvalJustDeviated( n, FALSE );
  1625.         break;
  1626.  
  1627.         case O_DEV | N_DEV :/* Node stays deviated but no transition */
  1628.         break;        /* -- do nothing -- */
  1629.  
  1630.          default:
  1631.         lprintf( stderr, "bad chk event (0x%2x) @ t=%.1f\n", e->type,
  1632.           d2ns( cur_delta ) );
  1633.       }
  1634.  
  1635.     if( (n->nflags & ACTIVE_CL) and (e->type & CHK) )
  1636.       {
  1637.         hptr  h;
  1638.  
  1639.         NEXTH( h, n->curr );
  1640.         (void) EnqueueHist( n, h, CHECK_PNT );
  1641.       }
  1642.       }
  1643.   }
  1644.  
  1645.  
  1646.  
  1647. /*
  1648.  * Events pending from a previous simulation run.  If the node is active at
  1649.  * this point, simply drop the event (the node is being resimulated) otherwise
  1650.  * re-schedule the pending event (as if it had been simulated).
  1651. */
  1652. private void EvalPending()
  1653.   {
  1654.     register evptr  ev;
  1655.     register nptr   n;
  1656.  
  1657.     for( ev = pend_evs; ev != NULL; ev = ev->nlink )
  1658.       {
  1659.     n = ev->enode;
  1660.     if( not (n->nflags & ACTIVE_CL) )
  1661.         enqueue_event( n, (int) ev->eval, (long) ev->delay, (long) ev->rtime );
  1662.       }
  1663.   }
  1664.  
  1665.  
  1666. private incstep( stop_time )
  1667.   long  stop_time;
  1668.   {
  1669.     evptr  evlist;
  1670.     long   step_t, refresh;
  1671.  
  1672.     refresh = (stop_time < 10) ? 1 : stop_time / 10;
  1673.     step_t = cur_delta + refresh;
  1674.     if( DoingFault ) step_t = max_time;        /* never refresh */
  1675.  
  1676.     while( (evlist = get_next_event( stop_time )) != NULL )
  1677.       {
  1678.     update_nodes( evlist );
  1679.     UpdateTransistors();
  1680.  
  1681.     EvalEventList();
  1682.  
  1683.     if( inp_evs )        EvalInputs();
  1684.     if( xinp_evs )        EvalXinputs();
  1685.     if( stim_evs )        EvalStimulus();
  1686.     if( pend_evs )        EvalPending();
  1687.  
  1688.     FreeEventList( evlist );
  1689.  
  1690.     if( cur_delta >= step_t )
  1691.       {
  1692.         do
  1693.           {
  1694.         lprintf( stdout, "time = %d.0\n", (int) d2ns( step_t ) );
  1695.         (void) fflush( stdout );
  1696.         step_t += refresh;
  1697.           }
  1698.         while( cur_delta >= step_t );
  1699.         if( analyzerON )
  1700.         UpdateWindow( cur_delta - 1 );
  1701.       }
  1702. #ifdef FAULT_SIM
  1703.     if( stop_early or int_received )
  1704.         return;
  1705. #endif
  1706.       }
  1707.     cur_delta = stop_time;
  1708. #ifndef FAULT_SIM
  1709.     if( analyzerON )
  1710.     UpdateWindow( cur_delta );
  1711. #endif
  1712.   }
  1713.  
  1714.  
  1715. private int fix_inc_nodes( nd )
  1716.   register nptr  nd;
  1717.   {
  1718.     register hptr  h;
  1719.     register lptr  l;
  1720.  
  1721.     if( nd->nflags & (ALIAS | MERGED) )
  1722.     return( 0 );
  1723.  
  1724.     if( (nd->nflags & ACTIVE_CL) and nd->t.punts != NULL )  /* shouldn't be */
  1725.       {
  1726.     for( h = nd->t.punts; h->next != NULL; h = h->next );
  1727.     h->next = freeHist;
  1728.     freeHist = nd->t.punts;
  1729.       }
  1730.  
  1731.     if( nd->nflags & (WAS_ACTIVE | CHANGED) )
  1732.     nd->t.cause = inc_cause;
  1733.  
  1734.     nd->nflags &= ~(VISITED|CHANGED|DEVIATED|STIM|ACTIVE_CL|WAS_ACTIVE);
  1735.  
  1736.     NEXTH( h, nd->curr );
  1737.     if( h != last_hist )        /* inconsistent ? */
  1738.       {
  1739.     register hptr  p;
  1740.  
  1741.     do
  1742.       {
  1743.         p = h;
  1744.         NEXTH( h, h );
  1745.       } while( h != last_hist );
  1746.     nd->curr = h = p;
  1747.       }
  1748.     else
  1749.     h = nd->curr;
  1750.  
  1751.     nd->c.time = h->time;
  1752.     nd->npot = h->val;
  1753.     if( h->inp )
  1754.     nd->nflags |= INPUT;
  1755.     else
  1756.     nd->nflags &= ~INPUT;
  1757.  
  1758.     for( l = nd->ngate; l != NULL; l = l->next )    /* fix transistors */
  1759.       {
  1760.     register tptr  t = l->xtor;
  1761.     t->state = compute_trans_state( t );
  1762.     t->tflags &= ~ACTIVE_T;
  1763.       }
  1764.     for( l = on_trans; l != NULL; l = l->next )
  1765.     l->xtor->tflags &= ~ACTIVE_T;
  1766.  
  1767.     return( 0 );
  1768.   }
  1769.  
  1770.  
  1771. /*
  1772.  * Start evaluating/activating the changed nodes.  This will schedulle other
  1773.  * events to get things rolling.  Special care is needed for changed nodes
  1774.  * that became inputs at time 0; we must ensure that their adjacent (src/drn)
  1775.  * transistors have the proper state, so things work out when the node
  1776.  * becomes undriven (if at all) and revaluated properly,
  1777.  */
  1778. private void startup_isim( n )
  1779.   nptr n;            /* the changed node */
  1780.   {
  1781.     pstg  stg;
  1782.  
  1783.     stg = GetConnList( n );
  1784.     ActivateStage( stg );
  1785.     if( stg->flags & INP_TRANS )    /* transition at time 0 => evaluate */
  1786.     (*curr_model)( n );
  1787.     else if( stg->flags & ONLY_INPUT )    /* node is an input at time 0 */
  1788.       {
  1789.     register lptr  l;
  1790.     register tptr  t;
  1791.  
  1792.     for( l = n->nterm; l != NULL; l = l->next )
  1793.       {
  1794.         t = l->xtor;
  1795.         t->state = compute_trans_state( t );
  1796.       }
  1797.     UndoStage( stg );
  1798.       }
  1799.     else                /* no transitions at time 0, undo */
  1800.     UndoStage( stg );
  1801.   }
  1802.  
  1803.  
  1804. /*
  1805.  * Main incremental simulation routine.  Move back to time 0, changing all
  1806.  * pending events to PENDING type.  Activate the clusters of all the
  1807.  * nodes in 'changed nodes' list and start simulating until we reach the
  1808.  * current time.  Make sure that the whole network is in a consistent state
  1809.  * before returning.
  1810.  */
  1811. public void incsim( ch_list )
  1812.   iptr  ch_list;
  1813.   {
  1814.     long  stop_time;
  1815.  
  1816.     o_nevals = nevals;
  1817.     nevals = i_nevals;
  1818.     o_nevent = nevent;
  1819.     sm_stat |= INCR_SIM;
  1820.  
  1821.     stop_time = cur_delta;
  1822.     cur_delta = sim_time0;
  1823.  
  1824.     (void) back_sim_time( cur_delta, TRUE );
  1825.  
  1826.     modelp = first_model;            /* initialize the model */
  1827.     curr_model = model_table[ modelp->val ];
  1828.     modelp = modelp->next;
  1829.     if( modelp != NULL )
  1830.     (void) EnqueueOther( CHNG_MODEL, (long) modelp->time );
  1831.  
  1832.     if( ch_list != NULL )
  1833.       {
  1834.     register iptr  ip;
  1835.  
  1836.     if( stop_time != 0 )        /* work to do ? */
  1837.       {
  1838.         for( ip = ch_list; ip != NULL; ip = ip->next )
  1839.         ip->inode->nflags |= VISITED;    /* set VISITED on all nodes */
  1840.       }
  1841.     else
  1842.       {
  1843.         while( (ip = ch_list) != NULL )
  1844.           {
  1845.         ch_list = ch_list->next;
  1846.         ip->inode->nflags &= ~(VISITED);
  1847.         FreeInput( ip );
  1848.           }
  1849.       }
  1850.  
  1851.     while( (ip = ch_list) != NULL )
  1852.       {
  1853.         ch_list = ch_list->next;
  1854.         if( ip->inode->nflags & VISITED )
  1855.         startup_isim( ip->inode );
  1856.         FreeInput( ip );
  1857.       }
  1858.       }
  1859.  
  1860.     incstep( stop_time );
  1861.  
  1862.     rm_inc_events( FALSE );
  1863.  
  1864.     walk_net( fix_inc_nodes, (char *) 0 );
  1865.  
  1866.     sm_stat &= ~INCR_SIM;
  1867.     i_nevals = nevals;
  1868.     nevals = o_nevals;
  1869.     nevent = o_nevent;
  1870.   }
  1871.  
  1872.  
  1873. #ifdef FAULT_SIM
  1874. public void init_faultsim()
  1875.   {
  1876.     o_nevals = nevals;
  1877.     nevals = i_nevals;
  1878.     o_nevent = nevent;
  1879.     sm_stat |= INCR_SIM;
  1880.     old_cur_delta = cur_delta;
  1881.     cur_delta = sim_time0;
  1882.     pending_evs = back_sim_time( cur_delta, TRUE + TRUE );
  1883.     fault_mode = TRUE;
  1884.   }
  1885.  
  1886.  
  1887. public void end_faultsim()
  1888.   {
  1889.     walk_net( fix_inc_nodes, (char *) 0 );
  1890.     cur_delta = old_cur_delta;
  1891.     requeue_events( pending_evs, TRUE );
  1892.     fault_mode = FALSE;
  1893.     sm_stat &= ~INCR_SIM;
  1894.     i_nevals = nevals;
  1895.     nevals = o_nevals;
  1896.     nevent = o_nevent;
  1897.   }
  1898.  
  1899.  
  1900. private int fix_fault_nodes( nd )
  1901.   register nptr  nd;
  1902.   {
  1903.     register lptr  l;
  1904.  
  1905.     if( not (nd->nflags & (ALIAS | MERGED)) )
  1906.       {
  1907.     nd->nflags &= ~(VISITED|CHANGED|DEVIATED|STIM|ACTIVE_CL|WAS_ACTIVE);
  1908.  
  1909.     if( nd->curr == &nd->hchange )
  1910.       {
  1911.         register hptr  h;
  1912.  
  1913.         NEXTH( h, nd->curr );
  1914.         nd->curr = (h == last_hist) ? &nd->head : h;
  1915.       }
  1916.  
  1917.         /* only mark transistors as non-activate for next faultsim */
  1918.     for( l = nd->ngate; l != NULL; l = l->next )
  1919.       {
  1920.         register tptr  t = l->xtor;
  1921.         t->tflags &= ~ACTIVE_T;
  1922.       }
  1923.     for( l = on_trans; l != NULL; l = l->next )
  1924.         l->xtor->tflags &= ~ACTIVE_T;
  1925.       }
  1926.     return( 0 );
  1927.   }
  1928.  
  1929.  
  1930. public void faultsim( n )
  1931.   nptr  n;
  1932.   {
  1933.     long   stop_time;
  1934.  
  1935.     stop_time = old_cur_delta;
  1936.  
  1937.     cur_delta = sim_time0;
  1938.     stop_early = 0;
  1939.  
  1940.     modelp = first_model;            /* initialize the model */
  1941.     curr_model = model_table[ modelp->val ];
  1942.     modelp = modelp->next;
  1943.     if( modelp != NULL )
  1944.     (void) EnqueueOther( CHNG_MODEL, (long) modelp->time );
  1945.  
  1946.     setup_triggers();
  1947.  
  1948.     n->nflags |= (VISITED | CHANGED);
  1949.     startup_isim( n );
  1950.  
  1951.     incstep( stop_time );
  1952.  
  1953.     rm_inc_events( TRUE );
  1954.  
  1955.     walk_net( fix_fault_nodes, (char *) 0 );
  1956.   }
  1957. #endif
  1958.